/*
    作者：zx
    时间：2022.11.24
    描述：信号量
*/

#include "ipc/semaphore.h"
#include "core/task.h"
#include "cpu/irq.h"
void sema_init(semaphore_t * semaphore, int init_count)
{
    semaphore->value = init_count;
    list_init(&semaphore->wait_list);
}

// 等信号、请求资源、相当于P操作
void sema_wait(semaphore_t * semaphore)
{
    irq_status_t irq_status = irq_enter_protection();
    if(semaphore->value > 0)
    {
        semaphore->value--;
    } 
    else
    {
        task_t * curr_task = curr_task_get();
        task_remove_ready(curr_task);
        list_insert_last(&semaphore->wait_list, &curr_task->wait_node);
        task_manager_update();  
    }
    irq_quit_protection(irq_status);
}

// 发信号、释放资源、相当于V操作
void sema_notify(semaphore_t * semaphore)
{
    irq_status_t irq_status = irq_enter_protection();
    if( list_count(&semaphore->wait_list) > 0)
    {
        list_node_t * task_wait_node = list_remove_first(&semaphore->wait_list);
        task_t * task = list_node_parent(task_wait_node, task_t, wait_node);
        task_set_to_ready(task);
        task_manager_update();
    }
    else 
    {
        semaphore->value++;
    }
    irq_quit_protection(irq_status);
}

int sema_value(semaphore_t * semaphore)
{
    irq_status_t irq_status = irq_enter_protection();
    int value = semaphore->value;
    irq_quit_protection(irq_status);
    return value;
}